<template>
  <div class="goodscat_container">
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>商品分类</el-breadcrumb-item>
    </el-breadcrumb>
    <el-card class="box-card">
      <el-row>
        <el-col :span="1">
          <el-button type="primary" @click="addCat">添加分类</el-button>
        </el-col>
      </el-row>
      <!-- 引用全局声明的组件tree-table -->
      <!-- 去掉表格的复选框列 :selection-type="false" -->
      <!-- 去掉表格的折叠列 :expand-type="false" -->
      <!-- 是否显示序号列 show-index-->
      <!-- 索引列表头文本 index-text-->
      <!-- 是否显示纵向边框 显示直接加border -->
      <!-- 悬停时是否高亮显示当前行 show-row-hover 默认显示，改为false -->
      <!-- 注：vue-table-with-tree-grid中作用域插槽中原本用的是scope属性，控制台提示scope已经被抛弃，使用slot-scope代替scope属性 -->

      <tree-table :data="cateList" :columns="columns" :selection-type="false" :expand-type="false" show-index index-text="#" show-row-hover border class="tree_table">
        <!-- 是否有效列 -->
        <template slot="isvalid" slot-scope="scope">
          <!-- {{ scope.row.cat_deleted }} -->
          <!--scope.row.cat_deleted为false,数据没有删除，显示对勾。true显示×  -->
          <i v-if="!scope.row.cat_deleted" class="el-icon-success" style="color:lightgreen"></i>
          <i v-else class="el-icon-error" style="color:lightgreen"></i>
        </template>
        <!-- 排序列 -->
        <template slot="sort" slot-scope="scope">
          <!-- {{scope.row.cat_level}} -->
          <!-- scope.row.cat_level 值为0表示1级分类，1表示二级分类，2表示3级分类 -->
          <el-tag size="mini" v-if="scope.row.cat_level === 0">一级</el-tag>
          <el-tag type="success" size="mini" v-else-if="scope.row.cat_level === 1">
            二级
          </el-tag>
          <el-tag type="warning" size="mini" v-else>三级</el-tag>
        </template>
        <template slot="action" slot-scope="scope">
          <el-button type="primary" icon="el-icon-edit" size="mini" @click="editCat(scope.row)">
            编辑
          </el-button>
          <!--删除按钮-->
          <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteCat(scope.row.cat_id)">
            删除
          </el-button>
        </template>
      </tree-table>
      <!--分页 page-sizes数组可以指定每页的容量，可自己定义，设置成数组[1,2,5],表示pagesize可以取1,2,5三个值-->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="queryInfo.pagenum"
        :page-sizes="[2, 5, 10]"
        :page-size="queryInfo.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      >
      </el-pagination>
    </el-card>
    <!-- 点击【添加分类】按钮，弹出的对话框 -->
    <el-dialog title="添加分类" :visible.sync="addCatDialogVisible" width="50%" @close="addCatDialogClosed">
      <!-- 添加分类的表单 -->
      <el-form :model="catRuleForm" :rules="catRules" ref="catRuleForm" label-width="100px">
        <el-form-item label="分类名称：" prop="cat_name">
          <el-input v-model="catRuleForm.cat_name"></el-input>
        </el-form-item>
        <!-- 不需要输入校验，prop属性删除 -->
        <el-form-item label="父级分类：">
          <!-- 注意：这里面添加的不是如同上面的input文本框，而是级联选择框 -->
          <!-- options 指定数据源 -->
          <!-- props属性级联选择器配置选项 -->
          <!-- selectedKeys是一个数组，里面的元素是[一级菜单id,二级菜单id],
          可以通过该元素对象的change事件打印出来 -->
          <!-- 是否支持清空选项，默认为false，更改为true -->
          <!-- change-on-select是否允许选择任意一级的选项，默认为false,
            只能选择最后一级的选项,置为true。但是，在更新版本的组件库中有bug
            全局css+操作DOM的方式实现，点击文字，选中分类（一级、二级）。遍历
            li中的子元素span,使用click()方法-模拟鼠标选中单选框或者复选框
            @visible-change="elCascaderOnlick"
            @expand-change="elCascaderOnlick" -->
          <el-cascader v-model="selectedKeys" :options="parentCatList" :props="cascaderProps" @change="parentCatChange" ref="cascaderRef" class="remove_radio" change-on-select clearable></el-cascader>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addCatDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addCatPre">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 商品分类-【编辑】按钮点击，弹出对话框 -->
    <el-dialog title="提示" :visible.sync="editCatDialogVisible" ref="editDialogRef" width="50%" @close="editDialogClosed">
      <el-form :model="editRuleForm" :rules="catRules" ref="editRuleRef" label-width="100px">
        <el-form-item label="分类名称：" prop="cat_name"> <el-input v-model="editRuleForm.cat_name"></el-input> </el-form-item
      ></el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editCatDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editCatDialogPre">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  created() {
    this.getCateList();
  },
  data() {
    return {
      // 查询条件-分页相关变量
      queryInfo: {
        // type表示显示三层分类列表，不传值也默认显示三层分类
        type: 3,
        pagenum: 1,
        pagesize: 5
      },
      // 根据当前页pagenum和页面容量pagesize查询的当前页数据
      cateList: [],
      // 总数据条数,默认为0
      total: 0,
      // tree-table的列参数
      // 注意：在columns对象配置中，如果没有使用template这种作用域插槽，
      // prop列属性名称必须与请求数据中某个属性名保持一致。使用作用域插槽时，
      // 只需要template值和slot值保持一致，此时prop可以任意命名
      columns: [
        {
          label: '分类名称',
          prop: 'cat_name',
          width: '400px'
        },
        {
          label: '是否有效',
          prop: 'cat_deleted',
          minWidth: '50px',
          // type属性设置为显示模板
          type: 'template',
          // 作用域插槽模板名字
          template: 'isvalid'
        },
        {
          label: '排序',
          prop: 'score',
          type: 'template',
          template: 'sort'
        },
        {
          label: '操作',
          prop: 'likes',
          minWidth: '200px',
          type: 'template',
          // 模板列操作名字
          template: 'action'
        }
      ],
      // 【添加分类】按钮点击时，对话框显示状态值
      addCatDialogVisible: false,
      // 【编辑】按钮点击时，对话框显示状态码
      editCatDialogVisible: false,
      // 某行的分类数据对象
      catRuleForm: {
        // 父级分类的id，如果要添加一级分类，则id应为0
        cat_pid: 0,
        // 分类名称
        cat_name: '',
        // 默认要添加的分类等级
        cat_level: 0
      },
      // 编辑时分类名称对象
      editRuleForm: {},
      // 表单校验规则
      catRules: {
        cat_name: [
          { required: true, message: '请输入分类名称', trigger: 'blur' },
          { min: 1, max: 12, message: '长度在 1 到 12 个字符', trigger: 'blur' }
        ]
      },
      // 分类名占位符
      cat_id: 0,
      // 父级分类列表数据(只包含一级和二级)
      parentCatList: [],
      // 级联选择器的配置选项
      cascaderProps: {
        // 定义次级菜单的展开方式，hover表示经过即展开次级菜单
        expandTrigger: 'hover',
        // 表示菜单选项的值，最好唯一，此处指定为cat_id
        value: 'cat_id',
        // label表示将要看到的菜单项文本
        label: 'cat_name',
        // 指定选项的子选项为该选项的某个属性值，就是父子菜单数据靠哪个属性连接
        children: 'children'
        // 设置父子节点之间取消选中关联，2.14.1版本需要声明
        // checkedStrictly: true
      },
      // 选中的一级和二级选项构成的id数组
      selectedKeys: [],
      nme: ''
    };
  },
  // 修复element ui更新后，只有点击圆圈才能选中的问题，且点击圆点后，下拉框不会自动关闭，点击label无反应的问题
  // 1.解决做出选择后，下拉框自动关闭的问题
  // 2.解决点击标签，也能选中单选框radio， @visible-change="elCascaderOnlick"
  //  @expand-change="elCascaderOnlick"
  // 3.隐藏圆圈，在样式中设置
  watch: {
    // 侦听v-model属性值的selectedKeys变化，一旦变化执行隐藏下拉框的操作
    selectedKeys() {
      if (this.$refs.cascaderRef) {
        // 选中一级或者 选中某个二级后，下拉框自动关闭
        this.$refs.cascaderRef.dropDownVisible = false; // 监听值发生变化就关闭它
      }
    }
  },

  methods: {
    // 获取商品分类列表
    async getCateList() {
      const { data: res } = await this.$http.get('categories', {
        params: this.queryInfo
      });
      console.log(res.data);
      // 1.商品分类请求失败给出提示
      if (res.meta.status !== 200) {
        return this.$message.error('请求商品分类列表失败!');
      }
      // 2.商品分类请求成功
      this.cateList = res.data.result;
      // 总数据条数，分页中需要使用
      this.total = res.data.total;
    },
    // 处理页码变化时的事件监听
    handleCurrentChange(val) {
      // 当前页码赋给pagenum
      this.queryInfo.pagenum = val;
      // 重新发起数据请求
      this.getCateList();
    },
    // 处理每页容量变化时的监听
    handleSizeChange(size) {
      this.queryInfo.pagesize = size;
      this.getCateList();
    },
    // 添加分类的操作
    // 1.点击【添加分类】按钮，弹出对话框
    addCat() {
      // 获取一级和二级分类的数据列表，渲染在“添加分类”对话框中
      this.getParentCat();
      // 然后，弹出对话框
      this.addCatDialogVisible = true;
    },
    // 获取父类的分类列表数据(包括一级和二级分类，因为选中三级分类，不能再加子类了，会变成四级)
    async getParentCat() {
      // type:2表示获取一级和二级商品分类
      const { data: res } = await this.$http.get('categories', {
        params: { type: 2 }
      });
      if (res.meta.status !== 200) {
        return this.$message.error('请求父级分类数据失败！');
      }
      // 请求父级分类成功
      console.log(res.data);
      this.parentCatList = res.data;
    },
    // 级联菜单选择项发生变化时触发的事件
    parentCatChange() {
      console.log(this.selectedKeys);
      /**
       * 1.如果selectedKeys数组长度等于0，则表示没有选中任何父级分类，一级或二级分类
       * 2.如果该数组长度大于0，则表示选中了分类
       */
      if (this.selectedKeys.length > 0) {
        // 要添加菜单项的父级id,即cat_id总是是数组中最后一项的值。要添加菜单项所属级别cat_level是该数组的的长度
        this.catRuleForm.cat_pid = this.selectedKeys[this.selectedKeys.length - 1];
        // cat_level表示要添加几级分类？由于获取的是第一级和第二级分类，
        // 如：this.selectedKeys.length最大值就是2，表示即将添加的是三级分类
        this.catRuleForm.cat_level = this.selectedKeys.length;
      } else {
        this.catRuleForm.cat_pid = 0;
        this.catRuleForm.cat_level = 0;
      }
    },
    // 2.解决点击label文字显示选中
    // elCascaderOnlick() {
    //   const that = this;
    //   setTimeout(function() {
    //     // label+span+i
    //     // .el-cascader-node__label表示被选中的span
    //     document.querySelectorAll('.el-cascader-node__label').forEach(el => {
    //       el.onclick = function() {
    //         // 点击选项文本，让其前一个兄弟元素也被点击
    //         /*
    //         原生对象的click()和onclick的区别和联系
    //         联系：两者的效果一样
    //         区别：
    //         1.click()方法是真正的用程序去点击，触发了onclick()事件。click()方法用于模拟checkbox或者
    //         radiobox的一次鼠标点击
    //         2.onclick()事件只是调用了obj对象所指向的事件处理函数，只是调用函数而已，并未触发事件
    //         */
    //         // 获取元素节点的兼容，IE9+ 谷歌 火狐，this.previousElementSibling,IE6/7/8 this.previousSibling表示前面的一个元素节点
    //         this.previousElementSibling.click() || this.previousSibling.click();
    //         that.$refs.cascaderRef.dropDownVisible = false;
    //       };
    //     });
    //     // .el-cascader-panel .el-radio直接表示label，点击label(类似单选框，用css样式设置了其隐藏，所以看不到)
    //     document.querySelectorAll('.el-cascader-panel .el-radio').forEach(el => {
    //       el.onclick = function() {
    //         that.$refs.cascaderRef.dropDownVisible = false;
    //       };
    //     });
    //   }, 100);
    // },
    // 1.对话框的关闭事件
    addCatDialogClosed() {
      // 1.1 重置表单域
      this.$refs.catRuleForm.resetFields();
      // 1.2 级联选择器重置为初始状态
      // 1.2.1 将储存父类id的数组清空
      this.selectedKeys = [];
      // 1.2.2 将已经在之前赋值的cat_pid,cat_level也置为初始值0
      this.catRuleForm.cat_pid = 0;
      this.catRuleForm.cat_level = 0;
    },
    // 2.点击对话框【确定】按钮事件
    addCatPre() {
      // 表单校验
      this.$refs.catRuleForm.validate(async valid => {
        if (!valid) return;
        // this.$message.success('添加分类表单数据校验成功!');
        // 预校验成功，就把数据参数对象catRuleForm提交到后台
        const { data: res } = await this.$http.post(
          'categories',
          this.catRuleForm // 窗口关闭事件中，已经更新了要传递的参数catRuleForm
        );
        console.log(res);
        if (res.meta.status !== 201) {
          return this.$message.error('添加分类操作失败！');
        }
        // 添加到后台成功后
        // 1.提示添加分类选项成功
        this.$message.success('添加分类操作成功!');
        // 2.关闭对话框
        this.addCatDialogVisible = false;
        // 3.重新调用获取分类请求方法
        this.getCateList();
      });
      console.log(this.catRuleForm);
    },
    // 【编辑】按钮对应方法
    async editCat(role) {
      console.log(role.cat_id);
      this.editCatDialogVisible = true;
      // 根据id查询当前行所在分类名称
      const { data: res } = await this.$http.get(`categories/${role.cat_id}`);
      console.log(res);
      // 请求失败，给出提示
      if (res.meta.status !== 200) {
        return this.$message.error('请求分类名称失败!');
      }
      // 请求成功
      // 把后台请求到当前行分类名赋给表单对应变量
      this.editRuleForm = res.data;
      // 测试代码
      console.log(this.editRuleForm);
    },
    // 关闭对话框，重置表单域
    editDialogClosed() {
      this.$refs.editRuleRef.resetFields();
      this.editRuleForm.cat_name = '';
    },
    // 【编辑】操作弹出的对话框的【确定】-预校验
    editCatDialogPre() {
      this.$refs.editRuleRef.validate(async valid => {
        if (!valid) return; // 预校验失败
        // 预校验成功
        // 1.编辑提交请求 参数：分类id、编辑分类名称cat_name
        const { data: res } = await this.$http.put(`categories/${this.editRuleForm.cat_id}`, {
          cat_name: this.editRuleForm.cat_name
        });
        console.log(res.data);
        // 2.提交请求失败
        if (res.meta.status !== 200) {
          return this.$message.error('提交分类名称更改请求失败!');
        }
        // 2.1 提交更改成功提示
        this.$message.success('提交分类名称更改请求成功!');
        // 2.2 关闭对话框
        this.editCatDialogVisible = false;
        // 2.3 重新请求分类数据
        this.getCateList();
      });
    },
    // 【删除】按钮点击时事件
    async deleteCat(id) {
      const result = await this.$messageBox
        .confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .catch(error => error);
      console.log(result);
      // 1.result值为cancel,表示点击了“取消”按钮
      // 2.result值为confirm表示点击了“确定”按钮
      if (result !== 'confirm') {
        return this.$message.error('您取消了删除当前分类的操作!');
      }
      // 3.点击 确定 按钮，要删除当前行数据，发送请求
      const { data: res } = await this.$http.delete(`categories/${id}`);
      console.log(res);
      // 3.1 删除分类成功提示
      this.$message.success('您成功删除当前分类数据!');
      // 3.2 重新请求分类列表
      this.getCateList();
    }
  }
};
</script>

<style lang="less" scoped>
.goodscat_container {
  .tree_table {
    margin-top: 15px;
  }
  /* 级联选择器的宽度 */
  .el-cascader {
    width: 100%;
  }
  /* 隐藏级联选择器选项前的单选框，声明未全局样式才能生效 */
  /* .el-radio {
    color: #606266;
    cursor: pointer;
    visibility: hidden; // 加上这一行
    margin-right: 30px;
  } */
  /* 级联选择高度过长,在全局样式中设置才生效 */
  /* .el-cascader-menu{
    height: 100px;
  } */
}
</style>
